unit Storage;

interface

uses SysUtils, Classes, Forms, IniFiles, TypInfoUtils;

type
  TControlStorage = class(TComponent)
  private
    FIniFileName: string;
    FSaveFormCloseQuery: TCloseQueryEvent;
    FSaveFormShow: TNotifyEvent;
    procedure FormShow(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    function GetForm: TForm;
    procedure SetEvents;
    procedure RestoreEvents;
  protected
    property Form: TForm read GetForm;
    procedure Loaded; override;
    procedure RestoreControls;
    procedure SaveControls;
  public
    destructor Destroy; override;
  published
    property IniFileName: string read FIniFileName write FIniFileName;
  end;

procedure Register;

implementation


{ TControlStorage }

procedure TControlStorage.SetEvents;
begin
  if Form <> nil then begin
    FSaveFormShow := Form.OnShow;
    Form.OnShow := FormShow;
    FSaveFormCloseQuery := Form.OnCloseQuery;
    Form.OnCloseQuery := FormCloseQuery;
  end;
end;

procedure TControlStorage.RestoreEvents;
begin
  if Form <> nil then begin
    Form.OnShow := FSaveFormShow;
    Form.OnCloseQuery := FSaveFormCloseQuery;
  end;
end;

procedure TControlStorage.FormShow(Sender: TObject);
begin
  RestoreControls;
  if Assigned(FSaveFormShow) then FSaveFormShow(Sender);
end;

procedure TControlStorage.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  if Assigned(FSaveFormCloseQuery) then
    FSaveFormCloseQuery(Sender, CanClose);
  if CanClose and (Owner is TCustomForm) and (Form.Handle <> 0) then
    try
      SaveControls;
    except
      Application.HandleException(Self);
    end;
end;

destructor TControlStorage.Destroy;
begin
  if not (csDesigning in ComponentState) then begin
    RestoreEvents;
  end;
  inherited Destroy;
end;

procedure TControlStorage.RestoreControls;
var
  i: integer;
  ini: TIniFile;
  PropVal: string;
begin
  ini := TIniFile.Create(FIniFileName);
  if ini <> nil then
  try
    for i := 0 to Form.ComponentCount - 1 do begin
      if HasProperty(Form.Components[i], 'text') then begin
        PropVal := ini.ReadString(Form.Name, Form.Components[i].Name, '');
        SetStringPropertyIfExists(Form.Components[i], 'text', PropVal);
      end;
    end;
  finally
    ini.Free;
  end;
end;

procedure TControlStorage.SaveControls;
var
  i: integer;
  ini: TIniFile;
  PropVal: string;
begin
  Ini := TIniFile.Create(FIniFileName);
  if Ini <> nil then
  try
    for i := 0 to Form.ComponentCount - 1 do begin
      if HasProperty(Form.Components[i], 'text') then begin
        PropVal := GetStringPropertyIfExists(Form.Components[i], 'text');
        ini.WriteString(Form.Name, Form.Components[i].Name, PropVal);
      end;
    end;
  finally
    Ini.Free;
  end;
end;


function TControlStorage.GetForm: TForm;
begin
  if Owner is TCustomForm then Result := TForm(Owner)
  else Result := nil;
end;

procedure TControlStorage.Loaded;
var
  Loading: Boolean;
begin
  Loading := csLoading in ComponentState;
  inherited Loaded;
  if not (csDesigning in ComponentState) then begin
    if Loading then SetEvents;
  end;
end;


procedure Register;
begin
  RegisterComponents('IP', [TControlStorage]);
end;

end.
